package ws

import (
	"errors"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"

	"gitee.com/chenhonghua/ginorigin/log"
	"gitee.com/chenhonghua/ginorigin/random"
)

// 握手成功后，需要进行的业务处理，入参为握手成功的websocket的id和用户上下文
type ShakeSuccessFunc func(wsid string, c *gin.Context)

// @title ws握手接口
// @description 本质来说, WS服务在握手的过程中最开始也是HTTP请求, 然后再 Upgrade 到WS模式的,Upgrade函数接受三个参数, 一个是返回值套接字, 一个是请求套接字, 一个是返回值的头,而对于 Gin 的上下文 gin.Context 来说也是有这些数据的
// @param recieveMessageFunc RecieveMessageFunc "服务端收到客户端发送的消息时的处理逻辑"
// @param shakeSuccessFunc ShakeSuccessFunc "客户端初次握手时的处理逻辑"
func GinWebsocketHandler(recieveMessageFunc RecieveMessageFunc, shakeSuccessFunc ShakeSuccessFunc) func(c *gin.Context) {
	if nil == recieveMessageFunc {
		log.Fatal(errors.New("接收消息的处理过程不能未空"))
	}
	return func(c *gin.Context) {
		var wsUpgrader websocket.Upgrader = websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool { return true }, // 跨域放行
		}
		conn, err := wsUpgrader.Upgrade(c.Writer, c.Request, nil) // 将http连接升级成websocket连接
		if err != nil {
			c.JSON(http.StatusOK, gin.H{"msg":"升级websocket失败"})
			c.Abort()
			return
		}
		wsc := websocketConnection{
			id:                 random.RandomString(),
			socket:             conn,
			sendContent:        make(chan []byte),
			recieveMessageFunc: recieveMessageFunc,
		}
		if nil != shakeSuccessFunc {
			shakeSuccessFunc(wsc.id, c) // 握手成功，进行业务处理，比如上层业务系统自行维护一个“连接管理”，下层的连接管理不需要过多业务逻辑
		}
		log.Debug("申请websocket连接")
		manager.register <- wsc
		go wsc.recieve()
		go wsc.send()
	}
}
